package dao

import (
	"github.com/silenceper/wechat/v2/miniprogram"
	"github.com/silenceper/wechat/v2/officialaccount"
	"gorm.io/gorm"
	"micro-grpc-server/library/database"
	"micro-grpc-server/library/wechat"
	"micro-grpc-server/services/wechat/internal/conf"
	"sync"
)

type WechatDao struct {
	conf   *conf.Config
	Db     *gorm.DB
	Wechat *wechat.Wechat

	// 内部元素
	miniLock  sync.RWMutex
	miniMap   map[string]*miniprogram.MiniProgram
	mpLock    sync.RWMutex
	mpMap     map[string]*officialaccount.OfficialAccount

	scenarios map[string]struct{}
}

func NewDao(config *conf.Config) *WechatDao {
	return &WechatDao{
		conf:    config,
		Db:      database.NewMysql(config.Database),
		Wechat:  wechat.NewWechat(config.Redis),
		miniMap: map[string]*miniprogram.MiniProgram{},
		mpMap:   map[string]*officialaccount.OfficialAccount{},
		scenarios: map[string]struct{}{
			"chaping":  {},
			"nicetrip": {},
		},
	}
}

func (d *WechatDao) CheckScenario(scenario string) bool {
	_, ok := d.scenarios[scenario]
	return ok
}

//******** 公众号map ********//
func (d *WechatDao) GetMp(scenario string) *officialaccount.OfficialAccount {
	d.mpLock.RLock()
	mp, ok := d.mpMap[scenario]
	d.mpLock.RUnlock()

	if ok == true {
		return mp
	}
	return d.cacheMp(scenario)
}

func (d *WechatDao) cacheMp(scenario string) (mp *officialaccount.OfficialAccount) {
	switch scenario {
	case "chaping":
		mp = d.Wechat.MpWechat(d.conf.Chaping)
	}

	if mp != nil {
		d.mpLock.Lock()
		d.mpMap[scenario] = mp
		d.mpLock.Unlock()
	}

	return
}

//******** 小程序map ********//
func (d *WechatDao) GetMini(scenario string) *miniprogram.MiniProgram {
	d.miniLock.RLock()
	mini, ok := d.miniMap[scenario]
	d.miniLock.RUnlock()

	if ok == true {
		return mini
	}
	return d.cacheMini(scenario)
}

func (d *WechatDao) cacheMini(scenario string) (mini *miniprogram.MiniProgram) {
	switch scenario {
	case "testing_wxapp":
		mini = d.Wechat.MiniProgram(d.conf.TestingMini)
	}

	if mini != nil {
		d.miniLock.Lock()
		d.miniMap[scenario] = mini
		d.miniLock.Unlock()
	}

	return
}
